package gov.nist.ssd.swqb.gui.components;

import com.hp.hpl.jena.rdf.model.RDFNode;
import gov.nist.ssd.swqb.events.SelectEvent;
import gov.nist.ssd.swqb.events.StopEvent;
import gov.nist.ssd.swqb.gui.Main;
import gov.nist.ssd.swqb.listeners.SearchSelectListener;
import gov.nist.ssd.swqb.listeners.StopListener;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.swing.DefaultListModel;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.jdesktop.application.Application;
import org.jdesktop.application.ResourceMap;

/**
 *
 * @author Benjamin Herbomez <benjamin.herbomez@esial.com>
 */
public class SearchResult extends JPanel {
    
    public static int STATE_COLLAPSE = 0;
    public static int STATE_EXPAND = 1;
    private Map<String, RDFNode> results = new LinkedHashMap<String, RDFNode>();
    private int state = STATE_COLLAPSE;
    private Icon icon;
    private List<EventListener> listeners = new ArrayList<EventListener>();
    
    private JList list;
    
    private JButton stopButton;
    
    public SearchResult() {
        ResourceMap resourceMap = Application.getInstance().getContext().getResourceMap(Main.class);
        this.icon = resourceMap.getIcon("Search.icon");
        stopButton = new JButton("Stop search");
        stopButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                for (EventListener l : listeners) {
                    if (l instanceof StopListener) {
                        ((StopListener) l).stop(new StopEvent(this));
                    }
                }
            }
        });
        
        this.update();
    }
    
    public void setContent(Map<String, RDFNode> content) {
        this.results = content;
        this.update();
    }
    
    private void update() {
        this.removeAll();
        if (this.state == STATE_COLLAPSE) {
            this.generateCollapse();
        } else {
            this.generateExpand();
        }
        this.revalidate();
        this.repaint();
    }
    
    private void generateCollapse() {
        this.setLayout(new GridBagLayout());
        
        JButton b = new JButton(icon);
        b.setVerticalAlignment(SwingConstants.CENTER);
        b.setMargin(new Insets(8, 4, 8, 4));
        this.add(b);
        
        b.addActionListener(new ActionListener() {
            
            @Override
            public void actionPerformed(ActionEvent e) {
                state = STATE_EXPAND;
                update();
            }
        });
    }
    
    private void generateExpand() {
        //this.setPreferredSize(new Dimension(250, this.getHeight()));
        this.setLayout(new BorderLayout());
        
        DefaultListModel model = new DefaultListModel();
        int i = 0;
        for (String k : this.results.keySet()) {
            if(k.trim().equals(""))
                continue;
            model.setSize(model.size()+1);
            model.add(i++, k);
        }
        list = new JList(model);
        list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        list.addListSelectionListener(new ListSelectionListener() {     
            @Override
            public void valueChanged(ListSelectionEvent e) {
                RDFNode n = results.get((String)list.getSelectedValue());
                
                SelectEvent evt = new SelectEvent(e.getSource(), n);
                for (EventListener l : listeners) {
                    if (l instanceof SearchSelectListener) {
                        SearchSelectListener sl = (SearchSelectListener) l;
                        sl.selectPerformed(evt);
                    }
                }
            }
        });
        JPanel p = new JPanel();
        p.setLayout(new BorderLayout());
        p.add(list, BorderLayout.CENTER);
        JScrollPane scrollPan = new JScrollPane(p);
        
        scrollPan.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
        scrollPan.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scrollPan.setDoubleBuffered(true);
        scrollPan.setPreferredSize(new Dimension(300, 400));
        
        this.add(scrollPan, BorderLayout.CENTER);
        
        
        JButton b = new JButton(icon);
        b.setVerticalAlignment(SwingConstants.CENTER);
        b.setMargin(new Insets(8, 4, 8, 4));
        
        b.addActionListener(new ActionListener() {
            
            @Override
            public void actionPerformed(ActionEvent e) {
                state = STATE_COLLAPSE;
                update();
            }
        });
        
        JPanel pan = new JPanel();
        pan.setLayout(new GridBagLayout());
        pan.add(b);
        this.add(pan, BorderLayout.WEST);
        this.add(stopButton,BorderLayout.SOUTH);
    }
    
    
    public void addSearchSelectListener(SearchSelectListener l) {
        this.listeners.add(l);
    }
    
    public void removeSearchSelectListener(SearchSelectListener l) {
        this.listeners.remove(l);
    }
    
    public void addStopListener(StopListener l){
        this.listeners.add(l);
    }
    
    public void removeStopListener(StopListener l){
        this.listeners.remove(l);
    }

    public synchronized void addContent(String txt, RDFNode node) {
        if(txt.trim().equals(""))
            return;
        this.results.put(txt, node);
        if(this.state == STATE_EXPAND && list != null){   
            DefaultListModel model = (DefaultListModel) list.getModel();
            model.add(model.getSize(), txt);
        }
    }

    @Override
    public synchronized void paint(Graphics g) {
        super.paint(g);
    }

    public void clear() {
        this.setContent(new HashMap<String, RDFNode>());
        this.update();
    }
    
    public void collapse(){
        this.state = STATE_COLLAPSE;
        this.update();
    }
    
    public void expand(){
        this.state = STATE_EXPAND;
        this.update();
    }
    
    public void toggle(){
        if(this.state == STATE_COLLAPSE)
            this.state = STATE_EXPAND;
        else
            this.state = STATE_COLLAPSE;
        update();
    }
}
